# Copyright (C) 2008 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import logging
import string
import random
import re

import atom.url
import gdata.service
import gdata.apps.service
import gdata.alt.appengine
from google.appengine.api import memcache

import credentials

def GenPasswd():
  string = ''
  for i in range(7):
    string += random.choice('ABCDEF12345')
  return string


def CreateAccountFromModel(signer_model):
  """Attempt to create an account to satisfy the request."""
  service = CreateService()
  if not service:
    logging.info('Error creating service')
    return

  account_name = signer_model.choice
  password = GenPasswd()

  logging.info('Attempting to create account %s' % account_name)
  created = CreateAccount(service, account_name, password,
                          signer_model.first_name, signer_model.last_name)
  if created:
    signer_model.created = True
    signer_model.username = account_name
    signer_model.password = password
    signer_model.put()
    logging.info('Updated account %s' % account_name)

def CreateAccount(service, account_name, password, first_name, last_name):
  """Creates a Google Apps user account."""

  # Apps throws an error if you give an empty first or last name, so just
  # set them to a filler value if empty.
  if first_name == '':
    first_name = 'FirstName'
  if last_name == '':
    last_name = 'LastName'
  # Apps throws an error if name ends in period, so remove if exists
  if account_name[-1] == '.':
    account_name = account_name[0:-1]

  # Make sure name is not unicode
  account_name = str(account_name)
  try:
    entry = service.CreateUser(account_name, last_name, first_name, password)
  except Exception, e:
    logging.info('Exception creating account %s, %s' % (account_name, e))
    return False

  logging.info('Created account %s' % account_name)

  # The Apps API is sometimes slower than the 10s max URL fetch limit for GAE,
  # so it will not return an entry successfully, but oftentimes, it has
  # actually succeeded in creating the user.
  # So, instead of checking the entry object, we do a fast call (RetrieveUser)
  # to see if that user now exists.
  user = service.RetrieveUser(account_name)
  if user:
    return True
  else:
    return False


def CheckValidity(username):
  VALID_ACCOUNT_NAME = '[a-zA-Z0-9_.]+$'
  return re.match(VALID_ACCOUNT_NAME, username)

def CheckAvailability(username):
  if not CheckValidity(username):
    return 'invalid'

  service = CreateService()
  if service:
    try:
      service.RetrieveUser(username)
      return 'no'
    except gdata.apps.service.AppsForYourDomainException, e:
      # Assumption is that this means it's available
      return 'yes'
  else:
    return 'error'

def CreateService():
  service = gdata.apps.service.AppsService(domain='wavesandbox.com',
      email=credentials.email, password=credentials.password)
  service.http_client = gdata.alt.appengine.AppEngineHttpClient()
  # Initialize a client to talk to Google Data API services.
  if memcache.get('token') is not None:
    token = memcache.get('token')
    service.SetClientLoginToken(token)
    return service
  else:
    try:
      logging.info('Logging on')
      service.ProgrammaticLogin()
      token = service.GetClientLoginToken()
      # Tokens expire after 2 weeks. To be on safe side, we only cache for a
      # day.
      memcache.set('token', token, time=1440)
      return service
    except gdata.apps.service.AppsForYourDomainException, e:
      logging.info('CreateService Error %s' % e.message)
  return False
